/*
 * Ejercicio de PROG06 Ficheros Serializados.
 */
package ficheroSerializado;

import java.io.*;
import java.util.ArrayList;
import java.util.Scanner;

/**
 *
 * @author Jonatan S. Rodríguez Lantigua <jonatan.srl@gmail.com>
 */
public class gestionCliente {
//atributos privados de la clase 
     private static String ruta;
     private static ArrayList <Cliente> arrayCliente = new ArrayList <>();
     
     
 //Método privado  de la clase para establecer ruta para almacenar crearfichero.
     private static void establecerRutaFichero() throws Exception{
        String capturaRuta;
        BufferedReader entrada = new BufferedReader(new InputStreamReader(System.in));
                try{
                     capturaRuta = entrada.readLine();
                     gestionCliente.ruta = comprobarFileSeparator(capturaRuta) + "clientes.dat";
                     File ficheroCreado = new File(ruta);
                     ficheroCreado.createNewFile();
                     if (!ficheroCreado.exists()){
                         throw new Exception("No se puede establecer el fichero");
                     }
                }catch (FileNotFoundException error){
                     throw new Exception ("\"No se puede establecer el fichero, comprobar ruta o permisos, repita: \"");
                }catch (Exception error){
                     throw new Exception ("\"No se puede establecer el fichero, comprobar ruta o permisos, repita: \"");
                }
     }
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws Exception  {
        // TODO code application logic here
        Scanner clienteNif = new Scanner(System.in);
        boolean seguir;
        int nOpcion;
        eleccionFichero();
        
          seguir = true;      
        do{
            System.out.println("\n1.- Añadir cliente.");
            System.out.println("2.- Listar cliente.");
            System.out.println("3.- Buscar clientes.");
            System.out.println("4.- Borrar cliente.");
            System.out.println("5.- Borrar fichero de clientes completamente.");
            System.out.println("6.- Salir\n\n");
            
            System.out.print("Escriba el número de opción: ");
            nOpcion = seleccion();
            
            switch(nOpcion){
                case 1:     añadirCliente();
                    break;
                case 2:     
                       ArrayList lecturaCliente = leerCliente(); 
    
                       for (int i = 0; i<lecturaCliente.size(); i++){
                           Cliente objetoCliente = (Cliente) lecturaCliente.get(i);
                   System.out.println("\nCliente número " + (i+1));        
                   System.out.println("Nombre: \t" + objetoCliente.getNombre());
                   System.out.println("Dirección: \t" + objetoCliente.getDireccion());
                   System.out.println("NIF: \t\t" + objetoCliente.getNif());
                   System.out.println("Telefono: \t" + objetoCliente.getTelefono());
                   System.out.println("Deuda: \t\t" + objetoCliente.getDeuda());
                       }
                    break;
                case 3:     System.out.print("\nNombre o Nif del cliente a buscar: ");
                            busquedaCliente(clienteNif.nextLine());
                    break;
                case 4:     
                            System.out.print("\nNombre o Nif del cliente a borrar: ");
                            borrarCliente(clienteNif.nextLine());
                    break;
                case 5:     eliminarFichero(ruta);
                            eleccionFichero();
                    break;
                case 6:     seguir = false; //salida
                    break;
                default:
                    System.out.println("Elección incorrecta.\n"); 
                    seguir = true;
            }
            
            
       }while(seguir);
}
    
    /**
     * Método para capturar la selección del menú.
     * @return opcion devuelve valor entero de la selección del menú
     */
    public static int seleccion(){
        int opcion = 0;
        BufferedReader entrada = new BufferedReader(new InputStreamReader(System.in));
        boolean seguir;
            do{
                try{
                     opcion = Integer.parseInt(entrada.readLine());
                     seguir = false;
                }catch ( IOException | NumberFormatException error){
                    System.err.println("Selección un número, repita: ");
                    seguir = true;
                }catch (Exception error){
                    System.err.println("Eliga un opción válida, repita: ");
                    seguir = true;
                } 
            }while(seguir);  
        return opcion;
    }
    
    /**
     * Método estático de la clase para añadir clientes
     */
    static void añadirCliente() throws IOException, Exception{
        //debido a la cabecera del fichero hay tratarlo primero
        arrayCliente = leerCliente();
        File fichero = new File(ruta);
        if (fichero.exists()){
            fichero.delete();
        }
        boolean seguir;
                
        Scanner datos = new Scanner(System.in);
       do{ 
           //Crear un nuevo objeto cliente y añadir sus atributos
                 Cliente nuevoCliente = new Cliente();
               try{
                    seguir = false;
                    System.out.print("\nEscriba en nombre del cliente nuevo: ");
                    nuevoCliente.setNombre(datos.nextLine());
                    System.out.print("\nEscriba la dirección del cliente: ");
                    nuevoCliente.setDireccion(datos.nextLine());
                    System.out.print("\nEscriba en NIF: ");
                    nuevoCliente.setNif(datos.nextLine());
                    System.out.print("\nEscriba el telefóno: ");
                    nuevoCliente.setTelefono(datos.nextLine());
                    System.out.print("\nEscriba la deuda: ");
                    nuevoCliente.setDeuda(datos.nextLine());
                    
                    //Cargamos un arraylist con los clientes para escribirlos secuencial en el fichero
                    //para escribir una vez sola la cabezera del fichero.
                    arrayCliente.add(nuevoCliente);
                    System.out.print("\nAñadir nuevo cliente, 0-No 1-Si:  ");
                    int nOpcion = seleccion();
                    
                    switch(nOpcion){
                case 0:     seguir = false; //salida
                    break;
                case 1:     seguir = true; 
                    break;
                default:
                    seguir = true; // cualquier otra eleción continua
            }
               }catch (Exception error){
                   System.out.println(error.getMessage() + " repita datos de cliente: ");
                   seguir = true;
               } 
       }while(seguir); 
            
            FileOutputStream ficheroCreado = null;
            ObjectOutputStream clienteSerializado = null;
            
       try{  
             
             ficheroCreado = new FileOutputStream(ruta, true);
             clienteSerializado = new ObjectOutputStream(ficheroCreado);
             //extrar los objetos del array 
             int i;
                for ( i=0; i<arrayCliente.size(); i++){
                     Cliente listarArrayCliente = arrayCliente.get(i);
                     clienteSerializado.writeObject(listarArrayCliente);
                     clienteSerializado.flush();
                }

         }catch (FileNotFoundException error){
             System.err.println("No se puede encontrar el fichero.");    
         }catch (Exception error){
             System.err.println(error.getMessage());
         }finally{ 
        // siempre cerrar el buffer y fichero al terminar.
           clienteSerializado.close();
           ficheroCreado.close();
       }
    }

    /**
     * Método para listar objetos del fichero.
     * @throws IOException
     * @throws ClassNotFoundException 
     * 
     */
      static ArrayList <Cliente> leerCliente() throws IOException, ClassNotFoundException{
         ArrayList <Cliente> arrayClienteLeidos = new ArrayList <>();
         FileInputStream fichero = null;
         ObjectInputStream objetoLeer = null;
         Cliente objetoCliente;
         
         try{
             fichero = new FileInputStream(gestionCliente.ruta);
             objetoLeer = new ObjectInputStream(fichero);
             do{
             
             //convertir el objeto leida a tipo Cliente.
             objetoCliente = (Cliente) objetoLeer.readObject();
             //añadidos al arraylist para procesarlos posteriormente
             arrayClienteLeidos.add(objetoCliente);
             }while(objetoCliente != null);
             
         }catch (EOFException | ClassNotFoundException error){
             System.out.println("Procesado" );
         }catch (StreamCorruptedException error){
             System.out.println("Fallo cabezera fichero. " + error.getMessage());
         }finally{
        //Siempre cerrar el buffer y el fichero
         //objetoLeer.close();          
         fichero.close();
         }
         return arrayClienteLeidos;
      }
    
    /**
     * Método estático para verificar el modificador en las rutas de ficheros según S.O.
     * Sacado de los apuntes de DAM 1º
     * @param ruta
     * @return ruta tratada.
     */
     static String comprobarFileSeparator(String ruta){
        String separador = "\\";
            try{
                // Si estamos en Windows
                if (File.separator.equals(separador)){
                    separador = "/";
                    //Reemplazar las cadenas que coinciden
                    return ruta.replaceAll(separador,File.separator);
                }
                 //Captura error si ocurre java.util.regex.PatternSyntaxException
            }catch (Exception e) {
                    return ruta.replaceAll(separador + separador, File.separator);
                }
        return ruta;
    }
    /**
     * Metodo para eliminar fichero.
     * @param ruta 
     */      
    private static void eliminarFichero(String ruta){
        File fichero = new File(ruta);
        if (fichero.exists()){
            fichero.delete();
            System.out.println("Fichero " + ruta + " eliminado con exito.");  
        }else{
            System.out.println("No se ha podido eliminar el fichero " + ruta );
        }
   
    }
    /**
     * Método para limpiar fichero de objetos 
     * @param cadenaBuscar 
     * @throws IOException
     * @throws ClassNotFoundException 
     */
    private static void borrarCliente (String cadenaBuscar) throws IOException, ClassNotFoundException{
        FileOutputStream ficheroCreado = null;
        ObjectOutputStream clienteSerializado = null;
        ArrayList buscarCliente = leerCliente();
        int posicion = busquedaCliente(cadenaBuscar);
        if (posicion == -1){
            System.out.println("No se puede eliminar.");
        }else{
        buscarCliente.remove(posicion);
        File fichero = new File(ruta);
             if (fichero.exists()){
                fichero.delete();
             }
        try{
             ficheroCreado = new FileOutputStream(ruta, true);
             clienteSerializado = new ObjectOutputStream(ficheroCreado);
             //extrar los objetos del array 
             int i;
                for ( i=0; i<buscarCliente.size(); i++){
                     Cliente listarArrayCliente = (Cliente) buscarCliente.get(i);
                     clienteSerializado.writeObject(listarArrayCliente);
                     clienteSerializado.flush();
                }
             System.out.println("\nBorrado del cliente satisfactorio.");
         }catch (FileNotFoundException error){
             System.err.println("No se puede encontrar el fichero.");    
         }catch (Exception error){
             System.err.println(error.getMessage());
         }finally{ 
        // siempre cerrar el buffer y fichero al terminar.
           clienteSerializado.close();
           ficheroCreado.close();
       } 
      } 
    }
    /**
     * Método de la clase para buscar un cliente por nombre o nif.
     * @param cadenaBuscar 
     * @throws IOException
     * @throws ClassNotFoundException 
     * @return valor de la posición según el resultado de la busqueda.
     */
    private static int busquedaCliente(String cadenaBuscar) throws IOException, ClassNotFoundException{
        int posicion = -1;
        boolean exito = false;
        ArrayList buscarCliente = leerCliente();
        String cadenaCorregida = cadenaBuscar;
        int valorCadena = cadenaBuscar.length();
        if (valorCadena < 25){
           int i;
           for (i=0; i<(25 - valorCadena);i++){
           cadenaCorregida = cadenaCorregida.concat(" ");
           }
       }else if (valorCadena > 25){
           cadenaCorregida = cadenaBuscar.substring(0, 24);
       }  
        for (int i=0; i<buscarCliente.size(); i++){
            Cliente busquedaCliente = (Cliente) buscarCliente.get(i);
            //comparar para encontrar el cliente.
            if ((cadenaCorregida.equals(busquedaCliente.getNombre()))||(cadenaCorregida.equals(busquedaCliente.getNif()))){
                   System.out.println("\nCliente encontrado número " + (i+1));        
                   System.out.println("Nombre: \t" + busquedaCliente.getNombre());
                   System.out.println("Dirección: \t" + busquedaCliente.getDireccion());
                   System.out.println("NIF: \t\t" + busquedaCliente.getNif());
                   System.out.println("Telefono: \t" + busquedaCliente.getTelefono());
                   System.out.println("Deuda: \t\t" +busquedaCliente.getDeuda());
                   exito = true;
                   posicion = i;
            }
        }
            if (exito){
                System.out.println("\nFin de la busqueda.");
                
            }else {
                System.out.println("\nNo se ha encontrado coincidencias.");
            }
        return posicion;
    }

    private static void eleccionFichero() {
        boolean seguir;
        System.out.println("Gestión de cliente.\n");
        do{ 
            System.out.print("Eliga la ubicación del fichero clientes.dat, (ej: c:\\): ");
            try{
                establecerRutaFichero();
                seguir = false;
            }catch (Exception error){
                System.err.println(error.getMessage());
                seguir = true;
            }
        }while(seguir);
    }
 }

